package com.example.myjetpackdemo

import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.media.MediaActionSound
import android.os.Bundle
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.widget.Toast
import androidx.annotation.NonNull
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File

/**
 * 利用camerax做的一个简单的拍照应用
 * 实现功能有：
 * 聚焦，缩放，前置后置摄像头，闪光灯，保存拍照文件等等
 *
 */
class MainActivity : AppCompatActivity() {

    private lateinit var mImageCapture: ImageCapture//拍照，以及设置闪光灯

    private lateinit var cameraSelector: CameraSelector//得到和修改前置/后置摄像头

    private lateinit var camera: Camera//相机信息类，包括聚焦和缩放比例

    private lateinit var cameraProvider: ProcessCameraProvider//指定要与相机关联的生命周期

    private lateinit var preview: Preview//相机预览

    @SuppressLint("RestrictedApi")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //检查权限
        checkPermission()

        btn_takephone.setOnClickListener {
            takePhoto()
        }
        btn_qz.setOnClickListener {
            //得到是前置摄像头还是后置摄像头
            var lensFacing = cameraSelector.lensFacing

            cameraProvider.unbind(preview, mImageCapture)

            if (lensFacing == CameraSelector.LENS_FACING_FRONT) {
                initCamera(CameraSelector.LENS_FACING_BACK)
                btn_qz.text = "前置摄像头"
                Toast.makeText(this, "已打开后置摄像头", Toast.LENGTH_SHORT).show()
            } else if (lensFacing == CameraSelector.LENS_FACING_BACK) {
                initCamera(CameraSelector.LENS_FACING_FRONT)
                btn_qz.text = "后置摄像头"
                Toast.makeText(this, "已打开前置摄像头", Toast.LENGTH_SHORT).show()
            }
        }

        btn_sgd.setOnClickListener {
            if (mImageCapture.flashMode == ImageCapture.FLASH_MODE_ON) {
                mImageCapture.flashMode = ImageCapture.FLASH_MODE_OFF
                btn_sgd.text = "打开闪光灯"
                Toast.makeText(this, "闪光灯已关闭", Toast.LENGTH_SHORT).show()
            } else {
                mImageCapture.flashMode = ImageCapture.FLASH_MODE_ON
                btn_sgd.text = "关闭闪光灯"
                Toast.makeText(this, "闪光灯已打开", Toast.LENGTH_SHORT).show()

            }
        }


        // 缩放监听
        val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
            override fun onScale(detector: ScaleGestureDetector): Boolean {
                // 获取当前的摄像头的缩放比例
                val currentZoomRatio: Float = camera.cameraInfo.zoomState.value?.zoomRatio ?: 1F

                //得到显示界面可以缩放的范围（不知道不同机型会不会不一样，红米k40是1-10）
//                Log.d("MainActivity", "minZoomRatio:"+camera.cameraInfo.zoomState.value?.minZoomRatio)
//                Log.d("MainActivity", "maxZoomRatio:"+camera.cameraInfo.zoomState.value?.maxZoomRatio)


                // 获取用户捏拉手势所更改的缩放比例
                val delta = detector.scaleFactor
//                Log.d("MainActivity", "currentZoomRatio:"+currentZoomRatio)
//                Log.d("MainActivity", "scaleFactor:" + delta)
//                Log.d("MainActivity", "缩放:" + (currentZoomRatio * delta))
                // 更新摄像头的缩放比例，要在缩放范围内，否则是无效的
                camera.cameraControl.setZoomRatio(currentZoomRatio * delta)
                return true
            }


        }

        // 将 PreviewView 的触摸监听器绑定到缩放手势监听器上
        val scaleGestureDetector = ScaleGestureDetector(this, listener)

        //单击聚焦监听
        val listener2 = object : GestureDetector.SimpleOnGestureListener() {
            override fun onSingleTapConfirmed(event: MotionEvent?): Boolean {
                val x = event?.x ?: 0f
                val y = event?.y ?: 0f
                setFocus(x, y)
                return true
            }
        }
        val gestureDetector = GestureDetector(this, listener2)


        // 将 PreviewView 的触摸事件传递给缩放手势监听器上
        view_finder.setOnTouchListener { v, event ->
            scaleGestureDetector.onTouchEvent(event)
            gestureDetector.onTouchEvent(event)
            true
        }

    }

    /**
     * 设置聚焦
     */
    fun setFocus(x: Float, y: Float) {
        Log.d("MainActivity", "x:$x,y:$y")
        //聚焦动画
        animFocusView(focus_image_view, x, y, true)
        // 创建 MeteringPoint，命名为 factory
        val meteringPointFactory = view_finder.meteringPointFactory

        // 将 UI 界面的坐标转换为摄像头传感器的坐标
        val point = meteringPointFactory.createPoint(x, y)

        // 创建对焦需要用的 action
        val action = FocusMeteringAction.Builder(point).build()

        // 执行所创建的对焦 action
        camera?.cameraControl?.startFocusAndMetering(action)
    }

    /**
     * 聚焦动画
     */
    private fun animFocusView(v: View, focusX: Float, focusY: Float, isRing: Boolean) {
        v.visibility = View.VISIBLE
        v.x = focusX - v.width / 2
        v.y = focusY - v.height / 2

        // 圆环和圆饼是不同的View，因此得到的ViewPropertyAnimator是不同的
        val anim = v.animate()
        anim.cancel()

        if (isRing) {
            // 圆环
            v.scaleX = 1.6f
            v.scaleY = 1.6f
            v.alpha = 1f
            anim.scaleX(1f)
                .scaleY(1f)
                .setDuration(300)
                .withEndAction {
                    v.animate()
                        .alpha(0f)
                        .setDuration(1000)
                        .withEndAction { v.visibility = View.INVISIBLE }
                        .start()
                }
                .start()
        } else {
            // 圆饼
            v.scaleX = 0f
            v.scaleY = 0f
            v.alpha = 1f
            anim.scaleX(1f)
                .scaleY(1f)
                .setDuration(300)
                .withEndAction {
                    v.animate()
                        .alpha(0f)
                        .setDuration(1000)
                        .withEndAction { v.visibility = View.INVISIBLE }
                        .start()
                }
                .start()
        }
    }

    //拍照
    private fun takePhoto() {
        if (mImageCapture != null) {
            //播放系统拍照的声音
            MediaActionSound().play(MediaActionSound.SHUTTER_CLICK)
            val cretaeFile = cretaeFile()
            val outputFileOptions: ImageCapture.OutputFileOptions =
                ImageCapture.OutputFileOptions.Builder(cretaeFile).build()
            //public void takePicture(@NonNull Executor executor,
            //            final @NonNull OnImageCapturedCallback callback)
            //还有一个重载方法，可以将拍到的图片缓存在内存里，
            // 一般不做本地保存,只是展示的话,可以用这个
            mImageCapture?.takePicture(
                outputFileOptions,
                ContextCompat.getMainExecutor(this),
                object : ImageCapture.OnImageSavedCallback {
                    override fun onImageSaved(@NonNull outputFileResults: ImageCapture.OutputFileResults) {
                        Log.d("MainActivity", "absolutePath:${cretaeFile.absolutePath}")
                        btn_takephone.text = "保存成功"
                        btn_takephone.postDelayed(Runnable {
                            btn_takephone.text = "拍照"
                        }, 1000)
                    }

                    override fun onError(@NonNull exception: ImageCaptureException) {
                        btn_takephone.text = "保存失败"
                    }
                }

            )
        }
    }

    //初始化相机
    private fun initCamera(lensFacing: Int = CameraSelector.LENS_FACING_BACK) {

        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener(Runnable {

            try {
                cameraProvider = cameraProviderFuture.get()

                preview = Preview.Builder().build()


                //配置参数（后置摄像头等）注释的是自己配置的，其实系统提供了
                //CameraSelector.DEFAULT_FRONT_CAMERA
                //CameraSelector.DEFAULT_BACK_CAMERA
                //两个默认的配置方法(一个是前置摄像头，一个是后置摄像头)
                // Choose the camera by requiring a lens facing
//                cameraSelector =
//                    CameraSelector.Builder()
//                        .requireLensFacing(lensFacing)
//                        .build()
                if (lensFacing == CameraSelector.LENS_FACING_FRONT) {
                    cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
                } else {
                    cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
                }

                //图片拍摄用例
                //如需缩短照片拍摄的延迟时间，
                // 请将 ImageCapture.CaptureMode 设置为 CAPTURE_MODE_MINIMIZE_LATENCY。
                // 如需优化照片质量，请将其设置为 CAPTURE_MODE_MAXIMIZE_QUALITY。
                mImageCapture = ImageCapture.Builder()
                    .setFlashMode(ImageCapture.FLASH_MODE_AUTO)//闪光灯
//                    .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                    .build()


                //指定要与相机关联的生命周期，该生命周期会告知 CameraX 何时配置相机拍摄会话并确保相机状态随生命周期的转换相应地更改。
                camera = cameraProvider.bindToLifecycle(
                    this,
                    cameraSelector,
                    preview,
                    mImageCapture
                )
                //初始化缩放两倍
//                camera.cameraControl.setZoomRatio(2f)


                //相机预览
                preview?.setSurfaceProvider(view_finder.getSurfaceProvider())
            } catch (e: java.lang.Exception) {
                Log.d("MainActivity", "初始化相机错误" + e.message)
                e.printStackTrace()
            }


        }, ContextCompat.getMainExecutor(this))


    }


    //检查权限
    private fun checkPermission() {
//        Log.d("MainActivity", "0001")
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.CAMERA
            ) != PackageManager.PERMISSION_GRANTED
        ) {
//            Log.d("MainActivity", "0002")
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.CAMERA), 1000
            )
            return
        } else {
//            Log.d("MainActivity", "0003")
            initCamera()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {

//        Log.d("MainActivity", "1113")

        //super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1000) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED
            ) {
//                Log.d("MainActivity", "1114")

                //todo:permission granted
                checkPermission()
            } else {
//                Log.d("MainActivity", "1115")

                //todo:permission denied

            }
        }
    }


    //创建文件
    private fun cretaeFile(): File {
        val file = File(externalMediaDirs.firstOrNull()?.path + "/xphoto", "phonetest.jpg")
        when {
            file.exists() -> {

            }
            file.parentFile.exists() -> {
                file.createNewFile()
            }
            else -> {
                file.parentFile.mkdirs()
                file.createNewFile()
            }
        }
        return file
    }
}